#!/usr/bin/python

import os.path
from sys import argv
from math import ceil,floor,sqrt
import pprint
from xml.dom.minidom import parse
from xml.dom import Node
#import xml.dom.minidom

ARC_MULTI_FF = 0.6
ARC_MULTI_T = 1.8
ARC_MULTI_ST = 1.5

SPEED_MOD = (-1, 0, 1)

class Weapon:
    def __init__(self, id, weaponDict=None):
        self.id = id
        self.label = id
        self.ammo = 0
        self.arc = "f"

        self.plusAcc = False
        self.plusDam = False
        self.plusRange = False
        self.plusRof = False

        # Values below here can be initialized by the dictionary
        self.rating = 0 
        self.msize = 0
        self.acc = 0
        self.dam = 0
        self.rof = 0
        self.mb = 0

        self.hasIF = False
        self.hasAA = False
        self.hasSB = False
        self.hasGuided = False
        self.hasHaywire = False
        self.hasMR = False
        self.hasAC = False
        self.hasAP = False
        self.hasM = False
        self.hasT = False

        # Tac specific values
        self.tRange = 0
        self.tAE = 0

        # Blitz specific values
        self.bammo = 0 # Label only for R, LA, etc
        self.bRange = 0
        self.bAE = 0

        # If the dictionary exists, use it to initialize our values
        if weaponDict is not None:
            wr = weaponDict[id]
            self.rating = wr.rating
            self.msize = wr.msize
            self.dam = wr.dam
            self.acc = wr.acc
            self.rof = wr.rof
            self.mb = wr.mb
            self.hasIF = wr.hasIF
            self.hasAA = wr.hasAA
            self.hasSB = wr.hasSB
            self.hasGuided = wr.hasGuided
            self.hasHaywire = wr.hasHaywire
            self.hasMR = wr.hasMR
            self.hasAC = wr.hasAC
            self.hasAP = wr.hasAP
            self.hasM = wr.hasM
            self.hasT = wr.hasT
            self.tRange = wr.tRange
            self.tAE = self.tAE
            self.bRange = wr.bRange
            self.bAE = wr.bAE

    def getBaseCost(self, wepRef, size, verbose=False):

        # Set the rating for chassis reinforcement
        if self.rating == 's':
            self.rating = float(size)
        else:
            self.rating = wepRef.rating

        arcMulti = 1.0
        if self.arc == 'ff' or self.arc == 'fr':
            arcMulti = ARC_MULTI_FF
        elif self.arc == 't':
            arcMulti = ARC_MULTI_T
        elif self.arc == 'st':
            arcMulti = ARC_MULTI_ST

        # Do the weapon options
        #print "Weapon: plusAcc (%s) plusDam (%s) plusRange (%s) plusRof (%s)" \
        #    % (self.plusAcc, self.plusDam, self.plusRange, self.plusRof)
        label = self.id.upper()
        optionMulti = 1
        if self.plusAcc:
            optionMulti = 1.5
            label = "+".join([label, "acc"])
            self.acc = self.acc + 1
        if self.plusDam:
            optionMulti = 1.25
            label = "+".join([label, "dam"])
            self.dam = self.dam + 1
        if self.plusRange:
            optionMulti = 1.1
            label = "+".join([label, "range"])
            self.bRange = self.GetBlitzExRangeFromTac(self.GetTacRangeBase(self.bRange)+1)
            self.tRange = self.tRange + 1
        if self.plusRof:
            optionMulti = 1.1
            label = "+".join([label, "rof"])
            self.rof = self.rof + 1
        self.label = label            

        value = (float(self.rating) * arcMulti * optionMulti) 
        if verbose:
            print "    Weapon [%s] (%s) base costs:" % (self.label, self.arc)
            print "      rating (%.3f) * arc (%.3f) * option (%.3f) = (%.3f)" \
                % (float(self.rating), float(arcMulti), float(optionMulti), value)

        # Print the ammo sizes for comparision
        self.getAmmoSizes(wepRef, verbose)

        return value

    def GetTacRangeBase(self, blitzRange):
        tacRange = blitzRange / 3
        for x in range(3):
            tacRange = tacRange / 2
        print "Returning %s" % tacRange
        return tacRange

    def GetBlitzExRangeFromTac(self, tacBase):
        exRange = tacBase
        for x in range(3):
            exRange = exRange * 2
        exRange = exRange * 3            
        return exRange

    def getAmmoCost(self, wepRef, verbose=False):
        value = float(self.ammo) * wepRef.ammo
        if verbose:
            print "    Weapon [%s] ammo costs: (%.3f) * (%.3f) rounds = (%.3f)" \
                % (self.id, float(wepRef.ammo), float(self.ammo), value)
        return value

    def getAmmoSizes(self, wepRef, verbose=False):
        # Skip if we are a melee weapon
        if self.hasM:
            return

        sizes = { 1 :  [625, 2500, 10000, 40000, 160000, 640000], \
                  2 :  [80, 320, 1280, 5120, 20480, 81920], \
                  3 :  [25, 100, 400, 1600, 6400, 25600], \
                  4 :  [10, 40, 160, 640, 2560, 10240], \
                  5 :  [5, 20, 80, 320, 1280, 5120], \
                  6 :  [3, 12, 48, 192, 768, 3072], \
                  7 :  [2, 8, 32, 128, 512, 2048], \
                  8 :  [1, 4, 16, 64, 256, 1024], \
                  9 :  [1, 4, 16, 64, 256, 1024], \
                  10 : [1, 3, 9, 27, 81, 243], \
                  11 : [1, 3, 9, 27, 81, 243], \
                  12 : [1, 3, 9, 27, 81, 243], \
                  13 : [1, 3, 9, 27, 81, 243], \
                  14 : [1, 3, 9, 27, 81, 243], \
                  15 : [1, 3, 9, 27, 81, 243] \
                } 

        sb = sizes[wepRef.msize]
#        print "      For a weapon of size (%i) the bands are %i/%i/%i/%i/%i/%i" \
 #           % (wepRef.msize, sb[0], sb[1], sb[2], sb[3], sb[4], sb[5])
        esize = 0
        for size in sb:
            if self.ammo > size:
                esize = esize + 1
            else:
                break
        esize = wepRef.msize + esize                
        if verbose:
            print "      Effective weapon size of (%s) with ammo (%i) is (%i [base: %i])" % (self.label, self.ammo, esize, wepRef.msize)

class Perk:
    def __init__(self, id, perkDict=None):
        self.id = id
        self.cost = 0
        self.scost = 0
        self.rating = 1
        self.srating = 1
        self.label = ""
        self.isBlitz = False
        self.isAux = False
        self.isArmor = False
        self.refid = "" # right now, just the weapon name we reference
        self.printRating = False 

        # Initialize values from the dictionary
        if perkDict is not None:
            pr = perkDict[id]
            self.cost = pr.cost
            self.scost = pr.scost
            self.label = pr.label
            self.isBlitz = pr.isBlitz
            self.isAux = pr.isAux
            self.isArmor = pr.isArmor
            self.printRating = pr.printRating

    def getCost(self, rating, srating, size):
        cost = 0.0
        # Handle the special ratings here
        if self.cost != 's':
            cost = float(self.cost) * float(rating) + float(self.scost) * float(srating)

        # Double the cost for arms to account for both
        if self.id == "maniparm" or self.id == "toolarm" or self.id == "battlearm":
            # If rating is 0, then the arm isn't a punching arm, so use
            #  srating to determine the cost
            if rating == 0:
                cost = float(srating) * 0.5
            else:
                cost = float(rating) * 0.5
        elif self.id == "grapple":
            cost = 0.2 * float(srating) * float(rating)
        elif self.id == "passseat":
            # Extra special hack here - use the HG1e formula for Blitz OTV calculations
            #  since John decided it was too high w/o the root
            cost = sqrt(3 + rating)
        elif self.id == "jumpjets":
            cost = float(size) * float(rating)
        return cost

class Flaw:
    def __init__(self, id, flawDict=None):
        self.id = id
        self.cost = 0
        self.scost = 0
        self.rating = 1
        self.srating = 1
        self.label = ""
        self.isBlitz = False
        self.isAux = False
        self.isArmor = False
        self.refid = "" # right now, nothing?
        self.printRating = False 

        # Initialize values from the dictionary
        if flawDict is not None:
            fr = flawDict[id]
            self.cost = fr.cost
            self.scost = fr.scost
            self.label = fr.label
            self.isBlitz = fr.isBlitz
            self.isAux = fr.isAux
            self.isArmor = fr.isArmor
            self.printRating = fr.printRating

    def getCost(self, rating, srating, size):
        cost = 0.0
        # Handle the special ratings here
        cost = float(self.cost) * float(rating) + float(self.scost) * float(srating)
        return cost

    def getCost(self, rating, srating, armor, size):
        cost = 0.0
        if self.id == 'weakface-f' or self.id == 'weakface-r':
            # This is only called for weak facing
            cost = float(self.cost) * float(armor)
        else:
            cost = float(self.cost) * float(rating) + float(self.scost) * float(srating)
        return cost

class Model:
    def __init__(self, name):
        self.name = name
        self.deploymentRange = 0
        self.sensorRange = 0
        self.sensorMod = 0
        self.commRange = 0
        self.commMod = 0
        self.armor = 0
        self.pmoveTop = 0
        self.pmoveType = "W"
        self.smoveTop = 0
        self.smoveType = None
        self.maneuver = 0
        self.firecon = 0
        self.crew = 1
        self.size = 6
        self.actions = 0
        self.weapons = []
        self.perks = []
        self.flaws = []
        self.offval = 0
        self.defval = 0
        self.miscval = 0
        self.otv = 0
        self.gmean = 0
        self.hmean = 0
        self.blitzTV = 0

    def printThreatValues(self):
        print "(%i/%i/%i) = (%i/%i) TV = (%i) Blitz TV" % (self.offval, self.defval, self.miscval, self.otv, self.gmean, self.blitzTV)

    def printThreatValuesAsCSF(self):
        otvDiff = self.gmean - self.otv
        blitzTV_gmean = ceil(self.gmean / 10)
        blitzDiff = blitzTV_gmean - self.blitzTV
        print "%i,%i,%i,%i,%i,%i,%i,%i,%i" % (self.offval, self.defval, self.miscval, self.otv, self.gmean, otvDiff, self.blitzTV, blitzTV_gmean, blitzDiff)

    def printThreatValuesAsBBCode(self):
        otvDiff = self.gmean - self.otv
        blitzTV_gmean = ceil(self.gmean / 10)
        blitzDiff = blitzTV_gmean - self.blitzTV
        #print "(%4i/%4i/%4i)" % (self.offval, self.defval, self.miscval),
        print "|| %4i | %4i | %+5i ||  || %3i | %3i | %+4i ||" % (self.otv, self.gmean, otvDiff, self.blitzTV, blitzTV_gmean, blitzDiff)

    def printBlitzStats(self):
        # Get primary defense
        pmoveTop = ceil(self.pmoveTop / 6)
        pmoveCbt = ceil(pmoveTop / 2)
        # Check for decreased maneuver flaw first
        manuv = self.maneuver
        for flaw in self.flaws:
            if flaw.id == "dmaneuver" and flaw.refid == self.pmoveType:
                manuv = manuv - flaw.rating

        pmoveStopMod = manuv + SPEED_MOD[0]
        pmoveCbtMod  = manuv + SPEED_MOD[1]
        pmoveTopMod  = manuv + SPEED_MOD[2]
        print "DEFENSE: (%1s) %2i/%2i  %+1i / %+1i / %+1i" \
            % (self.pmoveType.upper(), pmoveCbt, pmoveTop, pmoveStopMod, pmoveCbtMod, pmoveTopMod)

        if self.smoveTop is not None and self.smoveTop > 0:
            smoveTop = (self.smoveTop / 6)
            smoveCbt = ceil(smoveTop / 2)

            #Check for decreased maneuver flaw
            manuv = self.maneuver
            for flaw in self.flaws:
                if flaw.id == "dmaneuver" and flaw.refid == self.smoveType:
                    manuv = manuv - flaw.rating

            smoveStopMod = manuv + SPEED_MOD[0]
            smoveCbtMod  = manuv + SPEED_MOD[1]
            smoveTopMod  = manuv + SPEED_MOD[2]
            print "DEFENSE: (%1s) %2i/%2i  %+1i / %+1i / %+1i" \
                % (self.smoveType.upper(), smoveCbt, smoveTop, smoveStopMod, smoveCbtMod, smoveTopMod)

        print "ATTACK:             %+1i / %+1i / %+1i" \
            % (2 + self.firecon, self.firecon, -3 + self.firecon)
        print "------"

        # Calculate actions
        actionCount = 1
        for perk in self.perks:
            if perk.id == 'automation':
                actionCount = actionCount + perk.rating
        print "Actions:   %i" % (int(actionCount))

        # Calculate auto com, detect
        autocomm = round(self.commRange ** (0.5))
        print "Detect:    %i  Sensors: %+i" % (int(self.sensorRange), int(self.sensorMod))
        print "Auto Comm: %i  Comm:    %+i" % (int(autocomm), int(self.commMod))

        # Calculate damage boxes
        sbox = 0
        lbox = 1
        hbox = 1
        cbox = 1

        sturdyperks = ['rcrew', 'rchassis', 'emedical', 'heatarmor', \
            'ammocontain', 'fuelcontain', 'easymodify', 'rlocarmor', 'sturdy_box' ]
        for perk in self.perks:
            if perk.id in sturdyperks:
                sbox = sbox + 1

        fragileperks = ['brittlearmor', 'fragilechassis', 'hazardammo', 'hazardfuel', 'weakpoint', 'expcrew', 'diffmodify', 'no_critical_box' ]
        for flaw in self.flaws:
            if flaw.id in fragileperks:
                cbox = cbox - 1
        if cbox < 0:
            cbox == 0                

        # Check for armor perks/flaws
        armorLabel = []
        for perk in self.perks:
            if perk.isArmor:
                if perk.printRating:
                    armorLabel.append("%s:%i" % (perk.label, perk.rating))
                else:
                    armorLabel.append("%s" % (perk.label))
        # Check for Rf, Rr
        armorText = "Armor: %i" % (int(self.armor))

        print "%s  Perks: %s" % (armorText, ", ".join(armorLabel))

        damageTrack = ["Damage Track: "]
        for box in range(0,sbox):
            damageTrack.append("[S]")
        for box in range(0,lbox):
            damageTrack.append("[L]")
        for box in range(0,hbox):
            damageTrack.append("[H]")
        for box in range(0,cbox):
            damageTrack.append("[C]")
        print " ".join(damageTrack)

        # Display chassis perks
        print "------"
        perkText = []
        for perk in self.perks:
            if perk.isBlitz:
                if perk.printRating:
                    perkText.append("%s:%i" % (perk.label, perk.rating))
                else:
                    perkText.append("%s" % (perk.label))
        for flaw in self.flaws:
            if flaw.isBlitz:
                if flaw.printRating:
                    perkText.append("%s:%i" % (flaw.label, flaw.rating))
                else:
                    perkText.append("%s" % (flaw.label))
        print "Perks/Flaws: %s" % (", ".join(perkText))                    

        # Display AUX perks
        auxText = []
        for perk in self.perks:
            if perk.isAux:
                if perk.printRating:
                    auxText.append("%s:%i" % (perk.label, perk.rating))
                else:
                    auxText.append("%s" % (perk.label))
        print "AUX Systems: %s" % (", ".join(auxText))                    

        # Calculate weapons
        print "Weapons:"
        for weapon in self.weapons:

            # Calculate range
            rangeText = None
            if weapon.hasT:
                rangeText = "%23s" % "THROWN".ljust(21)
            elif weapon.hasM:
                rangeText = "%23s" % ""
            else:
                rangeLR = ceil(weapon.bRange/2)
                rangeMR = ceil(rangeLR/2)
                rangeSR = ceil(rangeMR/2)
                rangePB = ceil(rangeSR/2)
                rangeText = "%3i /%3i /%3i /%3i /%3i" \
                    % (rangePB, rangeSR, rangeMR, rangeLR, weapon.bRange)

            # Calculate perks
            perks = []
            if weapon.rof > 0:
                perks.append("ROF %s" % weapon.rof)
            if weapon.hasIF:
                perks.append("IF")
            if weapon.bAE > 0:
                perks.append("AE:%s" % weapon.bAE)
            if weapon.hasAA:
                perks.append("AA")
            if weapon.hasSB:
                perks.append("SB")
            if weapon.hasGuided:
                perks.append("G")
            if weapon.hasHaywire:
                perks.append("H")
            if weapon.hasMR:
                perks.append("MR")
            if weapon.hasAC:
                perks.append("AC")
            if weapon.hasAP:
                perks.append("AP")
            if weapon.hasM:
                perks.append("M")
                weapon.dam = int(self.size) + int(weapon.dam)
            if weapon.hasT:
                perks.append("T")

            # Calculate ammo
            if weapon.arc == 'h' and weapon.ammo > 30:
                perks.append("R")
            if weapon.ammo < 9 and weapon.ammo > 0:
                perks.append("O" * int(weapon.ammo))

            # Check perks for a link
            for perk in self.perks:
                if perk.refid == weapon.id:
                    perks.append("%s(%s)" % (perk.label, weapon.label))
            perkText = ", ".join(perks)                

            print "  %16s  %2s %+2i %s x%2i %s" \
                % (weapon.label.ljust(16), weapon.arc.upper().ljust(2), \
                weapon.acc, rangeText, \
                weapon.dam, perkText)
        print "  %47s x%2i M" % ("PHYSICAL ATTACK (PUNCH/KICK/RAM)".ljust(47), int(self.size))                

    def getDefMod(self, speed, maneuver):
        '''
            HG Tac Movement Mods:
            0 = -3
            1-2 = -2
            3-4 = -1
            5-6 = +0
            7-9 = +1
            10-19 = +2
            20-99 = +3
            99+ = +4
        '''
        mod = 0
        if speed == 0:
            mod = -3
        elif speed > 0 and speed < 3:
            mod = -2
        elif speed > 2 and speed < 5:
            mod = -1
        elif speed > 4 and speed < 7:
            mod = 0
        elif speed > 6 and speed < 10:
            mod = 1
        elif speed > 9 and speed < 20:
            mod = 2
        elif speed > 19 and speed < 100:
            mod = 3
        elif speed > 00:
            mod = 4

        return mod + int(maneuver)



    def calc(self, perkDict, flawDict, weaponDict, verbose=False):
        if verbose:
            print "\nCalculating offensive value"
        self.calcOff(weaponDict, verbose)

        if verbose:
            print "\nCalculating defensive value"
        self.calcDef(verbose)

        if verbose:
            print "\nCalculating miscellaneous value"
        self.calcMisc(perkDict, flawDict, verbose)

        self.otv = ceil( (self.offval + self.defval + self.miscval) / 3 )
        self.gmean = ceil( (self.offval * self.defval * self.miscval)**(1.0/3.0) )
        self.hmean = ceil( 3.0 / (1.0 / self.offval + 1.0 / self.defval + 1.0 / self.miscval) )
        self.blitzTV = ceil( self.otv / 10)
        return

    def calcOff(self, weaponDict, verbose=False):
        total = 0

        value = 0
        for wep in self.weapons:
            wepRef = weaponDict[wep.id]
            wepCost = wep.getBaseCost(wepRef, self.size, verbose)
            value += wepCost
        total += value            
        if verbose:
            print "  (Costs for all Weapons) = (%.3f)\n" % (value)
        
        value = 0
        for wep in self.weapons:
            wepRef = weaponDict[wep.id]
            wepCost = wep.getAmmoCost(wepRef, verbose)
            value += wepCost
        total += value
        if verbose:
            print "  (Ammunition costs for all weapons) = (%.3f)\n" % (value)

        armRating = 0.0
        for perk in self.perks:
            if perk.id == 'maniparm' or perk.id == 'battlearm' or perk.id == 'toolarm':
                # If the arm is a non-punching arm, it will have a 0 rating
                if perk.rating != 0:
                    value = (float(perk.rating) * 0.5) ** 2
                    armRating += value
                    if verbose:
                        print "    Weapon Rating for punch costs:"
                        print "      rating ((%.3f) * (0.5))^2 = (%.3f)" % (float(perk.rating), value)
        if armRating > 0:
            total += armRating
            if verbose: 
                print "  (Punch Rating for all arms) = (%.3f)\n" % (armRating)

        multi = 1
        if self.firecon == 5:
            multi = 700
        elif self.firecon == 4:
            multi = 120
        elif self.firecon == 3:
            mutli = 24
        elif self.firecon == 2:
            multi = 6
        elif self.firecon == 1:
            multi = 2
        elif self.firecon == -1:
            multi = 0.5
        elif self.firecon == -2:
            multi = 0.333
        elif self.firecon == -3:
            multi = 0.25
        elif self.firecon == -4:
            multi = 0.2
        elif self.firecon == -5:
            multi = 0.167
        if verbose:
            print "  (Targeting System Multiplier) = (%.3f)" % (multi)

        value = multi * total
        if verbose:
            print "  (Targeting System Multiplier * Offensive Multiplier) = (%.3f * %.3f) = (%.3f)" % (multi, total, value)

        self.offval = ceil(value)
        if verbose:
            print "Offensive Score = (%.3f) = (%i)" % (value, self.offval)


    def calcDef(self, verbose=False):
        total = 0

        value = (float(self.armor) ** 2)
        total += value
        if verbose:
            print "  (Armor Rating)^2 = (%s)^2 = (%.3f)" % (self.armor, value)

        speed = 0
        moveType = 0
        if (self.smoveTop > self.pmoveTop):
            speed = self.smoveTop
            moveType = self.smoveType
        else:
            speed = self.pmoveTop
            moveType = self.pmoveType

        divisor = 25
        if moveType == "g" and self.smoveTop == 0:
            divisor = 40
        elif moveType == "r":
            divisor = 60
            
        value = (speed / divisor) ** 3
        total += value
        if verbose:
            print "  (fastest movement speed in kph / %.3f)^3 = (%.3f / %.3f)^3 = (%.3f)" % (divisor, speed, divisor, value)

        if (self.smoveTop < self.pmoveTop):
            speed = self.smoveTop
        else:
            speed = self.pmoveTop

        if speed > 0:
            divisor = 6
            value = (speed / 6) ** 2
            total += value
            if verbose:
                print "  (sum of speeds of all other movement types in kph / %.3f)^3 = (%.3f / %.3f)^3 = (%.3f)" % (divisor, speed, divisor,value)

        # TODO: Add space calculation

        multi = 1.0
        if self.maneuver == 3:
            multi = 9.0
        elif self.maneuver == 2:
            multi = 3.0
        elif self.maneuver == 1:
            multi = 1.5
        elif self.maneuver == -1:
            multi = 0.667
        elif self.maneuver == -2:
            multi = 0.5
        elif self.maneuver == -3:
            multi = 0.4
        elif self.maneuver == -4:
            multi = 0.333
        elif self.maneuver == -5:
            multi = 0.286
        elif self.maneuver == -6:
            multi = 0.25
        elif self.maneuver == -7:
            multi = 0.222
        elif self.maneuver == -8:
            multi = 0.2
        elif self.maneuver == -9:
            multi = 0.182
        elif self.maneuver == -10:
            multi = 0.167
            
        value = multi * total
        self.defval = ceil(value)
        if verbose:
            print "  Defense Multiplier = (%.3f)" % (total)
            print "  Manuever Multiplier * Defense Multiplier = (%.3f) * (%.3f) = (%.3f)" \
                % (total, multi, value)
            print "Defensive Score = (%.3f) = (%i)" % (value, self.defval)

    def calcMisc(self, perkDict, flawDict, verbose=False):
        total = 0

        value = (float(self.crew)) ** 3
        total += value
        if verbose:
            print "  (Total Actions)^3 = (%s)^3 = (%.3f)" % (self.crew, value)

        value = (float(self.commRange) / 10) ** 3
        total += value
        if verbose:
            print "  (Communication Range in km / 10)^3 = (%s / 10)^3 = (%.3f)" % (self.commRange, value)

        value = (float(self.sensorRange) / 2) ** 3
        total += value
        if verbose:
            print "  (Sensor Range in km / 2)^3 = (%s / 2)^3 = (%.3f)" % (self.sensorRange, value)

        value = (float(self.deploymentRange) / 50) ** 2
        total += value
        if verbose:
            print "  (Deployment Range in km / 50)^2 = (%s / 50)^2 = (%.3f)" % (self.deploymentRange, value)

        value = 0
        for perk in self.perks:
            perkRef = perkDict[perk.id]
            perkCost = perkRef.getCost(perk.rating, perk.srating, self.size)
            if verbose:
                print "    Perk (%s):(%s):(%s) costs (%.3f)" % (perk.id, perk.rating, perk.srating, perkCost)
            value += perkCost
        perkTotal = value 
        if verbose:
            print "  (Perk Point Total) = (%.3f)" % (perkTotal)
            
        value = 0
        for flaw in self.flaws:
            flawRef = flawDict[flaw.id]
            flawCost = flawRef.getCost(flaw.rating, flaw.srating, self.armor, self.size)
            if verbose:
                print "    Flaw (%s):(%s):(%s) costs (%.3f)" % (flaw.id, flaw.rating, flaw.srating, flawCost)
            value += flawCost
        flawTotal = value 
        if verbose:
            print "  (Flaw Point Total) = (%.3f)" % (flawTotal)

        value = float(self.sensorMod) + float(self.commMod) + perkTotal - flawTotal
        total += value ** 2
        if verbose:
            print "  (Sensor Score + Comm Score + Perk Score + Flaw Score)^2) ="
            print "    (%.3f + %.3f + %.3f - %.3f)^2 = (%.3f)^2 = (%.3f)" \
                % (float(self.sensorMod), float(self.commMod), perkTotal, flawTotal, value, value ** 2)
    
        self.miscval = ceil(total)
        if self.miscval < 0:
            self.miscval = 0
        if verbose:
            print "Miscellaneous Score: (%.3f) = (%i)" % (total, self.miscval)

''' Load reference data only '''
def loadData(filename):
    dataDict = {}
    #print ("Reading file (%s)" % filename)
    dom1 = parse(filename)
    #print dom1.toxml()
    dataNode = dom1.firstChild
    # Iterate over the children
    for child in dataNode.childNodes:
        att = child.attributes
        if child.nodeName == "weapon":
            weapon = Weapon(att['id'].value)
            if att.has_key("rating"):
                # Must remain a string to catch CR weirdness
                weapon.rating = att['rating'].value
            if att.has_key("ammo"):
                weapon.ammo = float(att['ammo'].value)
            if att.has_key("msize"):
                weapon.msize = int(att["msize"].value)
            if att.has_key("acc"):
                weapon.acc = int(att["acc"].value)
            if att.has_key("dam"):
                weapon.dam = int(att["dam"].value)
            if att.has_key("rof"):
                weapon.rof = int(att["rof"].value)
            if att.has_key("mb"):
                weapon.blitzAE = int(att["mb"].value)

            if att.has_key("if"):
                weapon.hasIF = True
            if att.has_key("aa"):
                weapon.hasAA = True
            if att.has_key("sb"):
                weapon.hasSB = True
            if att.has_key("guided"):
                weapon.hasGuided = True
            if att.has_key("haywire"):
                weapon.hasHaywire = True
            if att.has_key("mr"):
                weapon.hasMR = True
            if att.has_key("ac"):
                weapon.hasAC = True
            if att.has_key("ap"):
                weapon.hasAP = True
            if att.has_key("melee"):
                weapon.hasM = True
            if att.has_key("thrown"):
                weapon.hasT = True

            # Tac values
            if att.has_key("trange"):
                weapon.tRange = int(att['trange'].value)
            if att.has_key("tae"):
                weapon.tAE = int(att['tae'].value)

            # Blitz values
            if att.has_key("brange"):
                weapon.bRange = int(att['brange'].value)
            if att.has_key("bae"):
                weapon.bAE = int(att['bae'].value)

            dataDict[weapon.id] = weapon

        elif child.nodeName == "perk":
            perk = Perk(att['id'].value)
            if att.has_key("cost"):
                perk.cost = att['cost'].value
            if att.has_key("scost"):
                perk.scost = att['scost'].value
            if att.has_key("label"):
                perk.label = att['label'].value
            if att.has_key("isblitz"):
                perk.isBlitz = True
            if att.has_key("isaux"):
                perk.isAux = True
            if att.has_key("isarmor"):
                perk.isArmor = True
            if att.has_key("printrating"):
                perk.printRating = True
            dataDict[perk.id] = perk

        elif child.nodeName == "flaw":
            flaw = Flaw(att['id'].value)
            if att.has_key("cost"):
                flaw.cost = att['cost'].value
            if att.has_key("scost"):
                flaw.scost = att['scost'].value
            if att.has_key("label"):
                flaw.label = att['label'].value
            if att.has_key("isblitz"):
                flaw.isBlitz = True
            if att.has_key("isaux"):
                flaw.isAux = True
            if att.has_key("isarmor"):
                flaw.isArmor = True
            if att.has_key("printrating"):
                flaw.printRating = True
            dataDict[flaw.id] = flaw

    return dataDict
''' Parse an actual model file '''
def readFile(filename, perkDict, flawDict, weaponDict):
    model = Model(filename)

    #print ("Reading file (%s)" % filename)
    dom1 = parse(filename)
    dataNode = dom1.firstChild

    for child in dataNode.childNodes:
        if child.nodeName == "weapons":
            weapons = child.childNodes
            for weapon in weapons:
                att = weapon.attributes
                if att is not None:
                    weapon = Weapon(att['id'].value, weaponDict)
                    if att.has_key("arc"):
                        weapon.arc = att['arc'].value
                    if att.has_key("ammo"):
                        weapon.ammo = float(att['ammo'].value)
                    if att.has_key("plusacc"):
                        weapon.plusAcc = True
                    if att.has_key("plusdam"):
                        weapon.plusDam = True
                    if att.has_key("plusrange"):
                        weapon.plusRange = True
                    if att.has_key("plusrof"):
                        weapon.plusRof = True
                    model.weapons.append(weapon)

        elif child.nodeName == "perks":
            perks = child.childNodes
            for perk in perks:
                att = perk.attributes
                if att is not None:
                    perk = Perk(att['id'].value, perkDict)
                    if att.has_key('rating'):
                        perk.rating = float(att['rating'].value)
                    if att.has_key('srating'):
                        perk.srating = float(att['srating'].value)
                    if att.has_key('refid'):
                        perk.refid = att['refid'].value
                    model.perks.append(perk)
                

        elif child.nodeName == "flaws":
            flaws = child.childNodes
            for flaw in flaws:
                att = flaw.attributes
                if att is not None:
                    flaw = Flaw(att['id'].value, flawDict)
                    if att.has_key('rating'):
                        flaw.rating = float(att['rating'].value)
                    if att.has_key('srating'):
                        flaw.srating = float(att['srating'].value)
                    if att.has_key('refid'):
                        flaw.refid = att['refid'].value
                    model.flaws.append(flaw)
                
        elif child.nodeType is Node.ELEMENT_NODE:
            if child.firstChild is not None:
                data = child.firstChild.data
                if child.nodeName == "depRng":
                    model.deploymentRange = data
                elif child.nodeName == "sensorRng":
                    model.sensorRange = float(data)
                elif child.nodeName == "sensorMod":
                    model.sensorMod = float(data)
                elif child.nodeName == "commRng":
                    model.commRange = float(data)
                elif child.nodeName == "commMod":
                    model.commMod = float(data)
                elif child.nodeName == "armor":
                    model.armor = float(data)
                elif child.nodeName == "maneuver":
                    model.maneuver = float(data)
                elif child.nodeName == "firecon":
                    model.firecon = float(data)
                elif child.nodeName == "crew":
                    model.crew = float(data)
                elif child.nodeName == "bonusactions":
                    model.actions = float(data)
                elif child.nodeName == "pmoveTop":
                    model.pmoveTop = float(data) * 6
                elif child.nodeName == "pmoveType":
                    model.pmoveType = data
                elif child.nodeName == "smoveTop":
                    model.smoveTop = float(data) * 6
                elif child.nodeName == "smoveType":
                    model.smoveType = data
                elif child.nodeName == "size":
                    model.size = data

    return model


if __name__ == "__main__":
    verbose=False
    if len(argv) > 2 and argv[2] == 'true':
        verbose = True
    # Strip the path name from the current script to determine 
    #  the path to the datafiles
    dirname = os.path.dirname(argv[0])


    perkDict = loadData("%s/data/perks.xml" % dirname)
    flawDict = loadData("%s/data/flaws.xml" % dirname)
    weaponDict = loadData("%s/data/weapons.xml" % dirname)

    # Debug
    #pprinter = pprint.PrettyPrinter()
    #pprinter.pprint(weaponDict["sc"].acc)

    vehicleObj = readFile(argv[1], perkDict, flawDict, weaponDict)
    vehicleObj.calc(perkDict, flawDict, weaponDict, verbose)

    vehicleObj.printThreatValues()
    #print "%s," % (argv[1][2:-4]),
    #vehicleObj.printThreatValuesAsCSF()
    print "%25s" % (argv[1][2:-4]),
    vehicleObj.printThreatValuesAsBBCode()
    
    vehicleObj.printBlitzStats()
    #vehicleObj.printBlitzDatacard()

